Data Services Developer's Guide : Building Logical Entity Data Services
This page last changed on Jan 14, 2008 by tkatz.
eDocs Home > BEA AquaLogic Data Services Platform 3.0 Documentation > Data Services Developer's Guide
|
![]() | ALDSP Functions and Procedures |
The underlying data services can be physical or logical.
The beauty of a logical data service is that a return type is a model. Logical models capture the complexity of data integration once, and allow you to write clients that remain the same even when underlying physical data sources change.
The structure of a return type does not need to match the structure of the underlying data sources. Here, the CUSTOMER element has a 1-to-many relationship with its child element ADDRESS, and a 1-to-1 relationship with its other child element, CREDITRATING. Each complex element represents a separate physical data source.
<?xml version="1.0" encoding="UTF-8" ?> <xs:schema targetNamespace="ld:logical/CustomerProfile" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="CUSTOMER_PROFILE"> <xs:complexType> <xs:sequence> <xs:element name="CUSTOMER"> <xs:complexType> <xs:sequence> <xs:element name="CUSTOMER_ID" type="xs:string"/> <xs:element name="FIRST_NAME" type="xs:string"/> <xs:element name="LAST_NAME" type="xs:string"/> <xs:element name="EMAIL_ADDRESS" type="xs:string"/> <xs:element name="ADDRESS" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element name="ADDR_ID" type="xs:string"/> <xs:element name="CUSTOMER_ID" type="xs:string"/> <xs:element name="STREET_ADDRESS1" type="xs:string"/> <xs:element name="STREET_ADDRESS2" type="xs:string" minOccurs="0"/> <xs:element name="CITY" type="xs:string"/> <xs:element name="STATE" type="xs:string"/> <xs:element name="ZIPCODE" type="xs:string"/> <xs:element name="COUNTRY" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="CREDITRATING" maxOccurs="1"> <xs:complexType> <xs:sequence> <xs:element name="CUSTOMER_ID" type="xs:string"/> <xs:element name="RATING" type="xs:int" minOccurs="0"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
However, this structure is only by design. You could also have designed the return type with fewer elements, or in a flat structure, depending on how you want the service to return data.
The functions and procedures in a logical entity service are implemented in XQuery, which queries XML data much as SQL queries relational data. You can get information about any function or procedure by right-clicking it in the Overview tab.
A read function, for example, often takes no parameters and returns an instance of the return type.
In a logical entity service, you can designate one read function as primary. A primary read function captures the main data integration logic in the service. ALDSP generates the create, update, and delete procedures and the update map from the primary read function.
You can see the source code of the primary read function in the Source tab.
declare function tns:read() as element(tns:CUSTOMER_PROFILE)*{ for $CUSTOMER in cus1:CUSTOMER() return <tns:CUSTOMER_PROFILE> <CUSTOMER> <CUSTOMER_ID>{fn:data($CUSTOMER/CUSTOMER_ID)}</CUSTOMER_ID> <FIRST_NAME>{fn:data($CUSTOMER/FIRST_NAME)}</FIRST_NAME> <LAST_NAME>{fn:data($CUSTOMER/LAST_NAME)}</LAST_NAME> <EMAIL_ADDRESS>{fn:data($CUSTOMER/EMAIL_ADDRESS)}</EMAIL_ADDRESS> { for $ADDRESS in add:ADDRESS() where $CUSTOMER/CUSTOMER_ID eq $ADDRESS/CUSTOMER_ID return <ADDRESS> <ADDR_ID>{fn:data($ADDRESS/ADDR_ID)}</ADDR_ID> <CUSTOMER_ID>{fn:data($ADDRESS/CUSTOMER_ID)}</CUSTOMER_ID> <STREET_ADDRESS1>{fn:data($ADDRESS/STREET_ADDRESS1)}</STREET_ADDRESS1> <STREET_ADDRESS2?>{fn:data($ADDRESS/STREET_ADDRESS2)}</STREET_ADDRESS2> <CITY>{fn:data($ADDRESS/CITY)}</CITY> <STATE>{fn:data($ADDRESS/STATE)}</STATE> <ZIPCODE>{fn:data($ADDRESS/ZIPCODE)}</ZIPCODE> <COUNTRY>{fn:data($ADDRESS/COUNTRY)}</COUNTRY> </ADDRESS> } { for $CREDITRATING in cre:CREDITRATING() where $CUSTOMER/CUSTOMER_ID eq $CREDITRATING/CUSTOMER_ID return <CREDITRATING> <CUSTOMER_ID>{fn:data($CREDITRATING/CUSTOMER_ID)}</CUSTOMER_ID> <RATING?>{fn:data($CREDITRATING/RATING)}</RATING> </CREDITRATING> } </CUSTOMER> </tns:CUSTOMER_PROFILE> };
This read function returns a CUSTOMER_PROFILE element with a nested CUSTOMER element. Each CUSTOMER element has some number of ADDRESS elements and some number of CREDITRATING elements, where the CUSTOMER_ID in ADDRESS or CREDITRATING matches the CUSTOMER_ID in CUSTOMER. (The XQuery where clauses create table joins; see Add a Where Clause to a Query).
A logical entity service also typically has create, update, and delete procedures that act on underlying data sources. (The difference between a function and a procedure is that a procedure can have side effects, while a function cannot; see Data Service Types and Functions).
The CustomerProfile service has one create procedure, one update procedure, and two delete procedures. It also has a library procedure named stringToShort, which casts between two data types.
The Query Map view maps elements in data sources to the return type.
You can see the data sources on the left and the return type on the right. The blue lines map elements from the data sources to elements in the return type, showing how the return type receives data.
The green dashed lines between the data source blocks create joins, which become where clauses in the XQuery source, for example:
for $ADDRESS in add:ADDRESS() where $CUSTOMER/CUSTOMER_ID eq $ADDRESS/CUSTOMER_ID return
If you click a data element (not a container element) in the return type, you see its XQuery expression in the expression editor.
Notice that the mapping expressions use the built-in XQuery function fn:data, which extracts the data value from an XML element.
As you map elements visually in the Query Map, ALDSP creates XQuery source (for example, the read function shown above). The XQuery source is later converted to SQL queries, which you can see in Plan view.
In this query plan, you see the left outer join between the CUSTOMER and ADDRESS relational tables. This was created by the green dashed line drawn between the Customer and Address blocks in Query Map view.
When you build XQuery functions and procedures visually in Query Map view or by editing in Source view, you can test and run them on an ALDSP server. During server runtime, the functions and procedures are compiled into an executable query plan. Examine the query plan before you finalize the queries. Query Plan view gives you a peek into a query's execution logic and flags potential performance and memory problems. Building XQuery functions is an iterative process of test, view plan, and edit.
While Query Map view shows how a service reads from data sources, Update Map view shows how the service writes data to them.
The data sources are on the left, with updates coming from the return type on the right. The return type is available to client applications, where users update data.
The blocks on the left are update blocks. Each mapped element in an update block has an XQuery expression that defines how the element is updated. You can see the expression in the expression editor below the mapping area.
ALDSP generates the update map for you when you create a logical data service under these conditions:
(If you are using other data source types, you must edit the update template.)
You can then customize the update map and test it in Test view, without programming.
An application client uses the Service Data Objects programming model to update data sources. SDO is an application framework that allows you to update data sources while disconnected from them, using a flexible, optimistic concurrency model. You use only one API, the SDO API, to update multiple data sources -- relational, web service, XML files, and so on.
The Test view available in Data Services Studio works like a built-in client where you can easily test any function or procedure in the data service, before you build a custom client.
Testing a read function, for example, returns data as the service would to a client, in the shape of the return type.
To test a simple update, click the Edit button, edit some data in the result, then click Submit. When you test the read function again, the results show the change.
You can also test an SDO update by submitting a datagraph with a change summary (see Test an Update Procedure).
Contact BEA | Feedback | Privacy | (c) 2008 BEA Systems
![]() |
Document generated by Confluence on Jan 15, 2008 11:02 |